package com.wmh.baseservice.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wmh.baseservice.admin.pojo.AdRolePermissions;
import com.wmh.baseservice.admin.mapper.AdRolePermissionsMapper;
import com.wmh.baseservice.admin.service.AdInfoService;
import com.wmh.baseservice.admin.service.AdRolePermissionsService;
import com.wmh.baseservice.common.ex.ServiceException;
import com.wmh.baseservice.common.mybatisplus.methods.CommonServiceImpl;
import com.wmh.baseservice.common.redis.config.RedisConfig;
import com.wmh.baseservice.common.redis.utils.RedisUtil;
import com.wmh.baseservice.common.shiro.config.ShiroConfig;
import com.wmh.baseservice.common.utils.CommUtil;
import com.wmh.baseservice.common.utils.LogUtil;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author mmx generator
 * @since 2021-10-29
 */
@Service
public class AdRolePermissionsServiceImpl extends CommonServiceImpl<AdRolePermissionsMapper, AdRolePermissions> implements AdRolePermissionsService {

    @Resource
    private AdRolePermissionsService adRolePermissionsService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AdInfoService adInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setPer(Long id, List<AdRolePermissions> adRolePermissions) {
        //删除该账号原权限
        List<Long> list = adRolePermissionsService.list(new QueryWrapper<AdRolePermissions>().eq(AdRolePermissions.AD_ID, id).eq(AdRolePermissions.TYPE, 2)).stream().map(AdRolePermissions::getId).collect(Collectors.toList());
        if (list.size() != 0) {
            if (!adRolePermissionsService.removeByIds(list)) {
                throw new ServiceException();
            }
        }
        if (adRolePermissions.size() != 0) {
            //添加该账号权限
            if (!adRolePermissionsService.saveBatch(adRolePermissions)) {
                throw new ServiceException();
            }
        }
        //更新redis
        String project = RedisConfig.KEY_INFO;
        String key = "role_permissions_" + id + ShiroConfig.SHIRO_ADMIN + project;
        try {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            SimpleAuthorizationInfo infoRaw = (SimpleAuthorizationInfo) redisUtil.get(key);
            info.setRoles(CommUtil.checkNull(infoRaw) ? infoRaw.getRoles() : null);
            Set<String> permissions = adRolePermissions.size() == 0 ? new HashSet<>() : adRolePermissions.stream().filter(item -> CommUtil.checkNull(item.getPermissions())).map(AdRolePermissions::getPermissions).collect(Collectors.toSet());
            info.setStringPermissions(permissions);
            redisUtil.set(key, info);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.error("redis角色权限更新错误,key是:" + key + "。原因是:" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id, Integer type) {
        //删除角色权限
        AdRolePermissions adRolePermissions = adRolePermissionsService.getByIdForUpdate(id);
        if (!CommUtil.checkNull(adRolePermissions)) {
            throw new ServiceException();
        }
        List<AdRolePermissions> adRolePermissionsList = adRolePermissionsService.listForUpdate(type == 1 ? new QueryWrapper<AdRolePermissions>()
                .eq(AdRolePermissions.ROLE, adRolePermissions.getRole()) : new QueryWrapper<AdRolePermissions>()
                .eq(AdRolePermissions.PERMISSIONS, adRolePermissions.getPermissions()));
        List<Long> idList;
        idList = adRolePermissionsList.stream().map(AdRolePermissions::getId).collect(Collectors.toList());
        if (idList.size() != 0) {
            if (!adRolePermissionsService.removeByIds(idList)) {
                throw new ServiceException();
            }
        }
        idList = adRolePermissionsList.stream().filter(item -> CommUtil.checkNull(item.getAdId())).map(AdRolePermissions::getAdId).collect(Collectors.toList());
        if (type == 1) {
            //删除对应角色的账号
            if (idList.size() != 0) {
                if (!adInfoService.removeByIds(idList)) {
                    throw new ServiceException();
                }
            }
            //删除角色权限redis
            idList.forEach(item -> {
                String project = RedisConfig.KEY_INFO;
                String key = "role_permissions_" + item + ShiroConfig.SHIRO_ADMIN + project;
                redisUtil.del(key);
            });
        }else {
            idList.forEach(item -> {
                String project = RedisConfig.KEY_INFO;
                String key = "role_permissions_" + item + ShiroConfig.SHIRO_ADMIN + project;
                SimpleAuthorizationInfo info = (SimpleAuthorizationInfo) redisUtil.get(key);
                if (CommUtil.checkNull(info)){
                    SimpleAuthorizationInfo newInfo = new SimpleAuthorizationInfo();
                    newInfo.setRoles(info.getRoles());
                    info.getStringPermissions().remove(adRolePermissions.getPermissions());
                    newInfo.setStringPermissions(info.getStringPermissions());
                    redisUtil.set(key,newInfo);
                }
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInfo(AdRolePermissions adRolePermissions, String rawName) {
        if (!adRolePermissionsService.updateById(adRolePermissions)) {
            throw new ServiceException();
        }
        //更新所有用户角色权限
        List<AdRolePermissions> adRolePermissionsList = adRolePermissionsService.listForUpdate(adRolePermissions.getType() == 1 ? new QueryWrapper<AdRolePermissions>().eq(AdRolePermissions.ROLE, rawName)
                : new QueryWrapper<AdRolePermissions>().eq(AdRolePermissions.PERMISSIONS, rawName));
        adRolePermissionsList.forEach(item -> {
            if (adRolePermissions.getType() == 1) {
                item.setRole(adRolePermissions.getRole());
            } else {
                item.setPermissions(adRolePermissions.getPermissions());
            }
        });
        if (adRolePermissionsList.size() != 0) {
            if (!adRolePermissionsService.updateBatchById(adRolePermissionsList)) {
                throw new ServiceException();
            }
        }
        //更新redis队列
        adRolePermissionsList.forEach(item -> {
            String project = RedisConfig.KEY_INFO;
            String key = "role_permissions_" + item.getAdId() + ShiroConfig.SHIRO_ADMIN + project;
            try {
                SimpleAuthorizationInfo info = (SimpleAuthorizationInfo) redisUtil.get(key);
                if (CommUtil.checkNull(info)) {
                    Set<String> set = new HashSet<>();
                    SimpleAuthorizationInfo newInfo = new SimpleAuthorizationInfo();
                    if (adRolePermissions.getType() == 1) {
                        newInfo.setStringPermissions(info.getStringPermissions());
                        set.add(item.getRole());
                        newInfo.setRoles(set);
                    } else {
                        newInfo.setRoles(info.getRoles());
                        newInfo.setStringPermissions(adRolePermissionsList.size() == 0 ? new HashSet<>() : adRolePermissionsList
                                .stream().map(AdRolePermissions::getPermissions).collect(Collectors.toSet()));
                    }
                    redisUtil.set(key, newInfo);
                }
            } catch (Exception e) {
                e.printStackTrace();
                LogUtil.error("redis角色权限添加错误,key是:" + key + "。原因是:" + e.getMessage());
            }
        });
    }
}
